#ifndef _ALLOCATOR_INTERFACE_H
#define _ALLOCATOR_INTERFACE_H

#include<iostream>
#include <pthread.h>

namespace my
{
  class allocator_interface
  {
  public:
    virtual void reset_brk () = 0;
    virtual void * heap_lo () = 0;
    virtual void * heap_hi () = 0;
  };

  class libc_allocator : public virtual allocator_interface
  {
  public:
    static int init ();
    static void * malloc (size_t size);
    static void * realloc (void *ptr, size_t size);
    static void free (void *ptr);
    static int check ();
    void reset_brk ();
    void * heap_lo ();
    void * heap_hi ();
  };

  class allocator : public virtual allocator_interface
  {
  private:
    //freeLists[0] stores free blocks of MIN_SIZE <= size < 2 * MIN_SIZE. freeLists[i] stores
    //free blocks of MIN_SIZE * 2^i <= size < MIN_SIZE * 2^(i+1)
    static void *freeLists[];
    static __thread void *threadFreeLists[];
    static __thread int threadCounts[];
    static __thread int threadCountMinima[];
    static __thread size_t threadCacheSize;
    static __thread int versionID;
    static pthread_mutex_t listMutexes[];
    static void thread_init();
    static void * coalesce_blocks(void *ptr);
    static void * aggressive_coalesce_right(void *ptr, size_t new_size);
    static void * grow_thread_heap(int);
    static void * global_malloc(int);
    static int grow_heap(size_t);
    static void garbage_collect();

    /* Methods for heap checker */
    /* General method for checking a linked list of blocks. */
    static int validate_linked_list(void * head);

    /* Method for checking the linked list of blocks at freeLists[index]. */
    static int validate_free_list(int index);
    static int validate_thread_free_list(int index);

    /* Method for checking that a block in freeLists[index] is free and does indeed
     * in this list. */
    static int validate_free_block(void * blockptr, int index);
    static int validate_thread_free_block(void * blockptr, int index);

    /* Returns whether a given free block is in freeLists[index]. */
    static int is_in_free_list(void * blockptr, int index);
    static int is_in_thread_free_list(void * blockptr, int index);
  public:
    static int init ();
    static void * malloc (size_t size);
    static void * realloc (void *ptr, size_t size);
    static void free (void *ptr);
    static int check ();
    void reset_brk ();
    void * heap_lo ();
    void * heap_hi ();
  };


  class bad_allocator : public virtual allocator_interface
  {
  public:
    static int init ();
    static void * malloc (size_t size);
    static void * realloc (void *ptr, size_t size);
    static void free (void *ptr);
    static int check ();
    void reset_brk ();
    void * heap_lo ();
    void * heap_hi ();
  };

};
#endif /* _ALLOCATOR_INTERFACE_H */
